using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;

namespace Camalon.ColorPicker
{
	/// <summary>
	/// Summary description for TransparentColorDialog.
	/// </summary>
	internal class TransparentColorDialog : System.Windows.Forms.Form
	{
        internal event MouseEventHandler TxMouseUp;
        internal event MouseEventHandler TxMouseDown;
        internal event MouseEventHandler TxMouseMove;
        internal event EventHandler TxHidden;   


		public enum SizeX
		{
			Size1X,
			Size2X,
			Size3X,
			Size4X,
		}

        private bool _colorDialogMoving;
        private Point _mousePosition = Point.Empty;
        private SizeX _sizeX = SizeX.Size2X;

		private bool _isCircle = true;
		private TransparentForm _txForm;
		private const int OFFSET_BORDER = 8;


        private ToolStripMenuItem menuItemRound;
        private ContextMenuStrip contextMenuSizeX;
        private ToolStripMenuItem menuItem1x;
        private ToolStripMenuItem menuItem2x;
        private ToolStripMenuItem menuItem3x;
        private ToolStripMenuItem menuItem4x;
        private ToolStripMenuItem menuItemHide;
        private IContainer components;

		public TransparentColorDialog(   )
		{
			InitializeComponent();
			this.TransparencyKey = this.BackColor;
			this.TopMost = true;
			this.SetStyle( ControlStyles.DoubleBuffer, true);

            _txForm = new TransparentForm(this.contextMenuSizeX, _isCircle);
            //_txForm.Owner = this;//Slows the form moving
            _txForm.ShowInTaskbar = false;
            _txForm.StartPosition = FormStartPosition.Manual;

            Rectangle tfBounds = this.RectangleToScreen(this.ClientRectangle);
            tfBounds.Inflate(-OFFSET_BORDER, -OFFSET_BORDER);
            _txForm.Bounds = tfBounds;

            _txForm.Show(this);


            _txForm.MouseDown += new MouseEventHandler(tf_MouseDown);
            _txForm.MouseMove += new MouseEventHandler(tf_MouseMove);
            _txForm.MouseUp += new MouseEventHandler(tf_MouseUp);

            _txForm.Invalidate();
            this.TopMost = true;
            _txForm.TopMost = true;



		}


		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if(components != null)
				{
					components.Dispose();
				}
            
                if (_txForm != null && !_txForm.IsDisposed) _txForm.Dispose();
            }
			base.Dispose( disposing );
		}

		#region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
            this.components = new System.ComponentModel.Container();
            this.contextMenuSizeX = new System.Windows.Forms.ContextMenuStrip(this.components);
            this.menuItem1x = new System.Windows.Forms.ToolStripMenuItem();
            this.menuItem2x = new System.Windows.Forms.ToolStripMenuItem();
            this.menuItem3x = new System.Windows.Forms.ToolStripMenuItem();
            this.menuItem4x = new System.Windows.Forms.ToolStripMenuItem();
            this.menuItemRound = new System.Windows.Forms.ToolStripMenuItem();
            this.menuItemHide = new System.Windows.Forms.ToolStripMenuItem();
            this.contextMenuSizeX.SuspendLayout();
            this.SuspendLayout();
            // 
            // contextMenuSizeX
            // 
            this.contextMenuSizeX.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
            this.menuItem1x,
            this.menuItem2x,
            this.menuItem3x,
            this.menuItem4x,
            this.menuItemRound,
            this.menuItemHide});
            this.contextMenuSizeX.Name = "contextMenuSizeX";
            this.contextMenuSizeX.RenderMode = System.Windows.Forms.ToolStripRenderMode.Professional;
            this.contextMenuSizeX.ShowCheckMargin = true;
            this.contextMenuSizeX.ShowImageMargin = false;
            this.contextMenuSizeX.Size = new System.Drawing.Size(153, 158);
            // 
            // menuItem1x
            // 
            this.menuItem1x.Name = "menuItem1x";
            this.menuItem1x.Size = new System.Drawing.Size(152, 22);
            this.menuItem1x.Text = "1x";
            this.menuItem1x.Click += new System.EventHandler(this.menuItem1x_Click);
            // 
            // menuItem2x
            // 
            this.menuItem2x.Checked = true;
            this.menuItem2x.CheckState = System.Windows.Forms.CheckState.Checked;
            this.menuItem2x.Name = "menuItem2x";
            this.menuItem2x.Size = new System.Drawing.Size(152, 22);
            this.menuItem2x.Text = "2x";
            this.menuItem2x.Click += new System.EventHandler(this.menuItem2x_Click);
            // 
            // menuItem3x
            // 
            this.menuItem3x.Name = "menuItem3x";
            this.menuItem3x.Size = new System.Drawing.Size(152, 22);
            this.menuItem3x.Text = "3x";
            this.menuItem3x.Click += new System.EventHandler(this.menuItem3x_Click);
            // 
            // menuItem4x
            // 
            this.menuItem4x.Name = "menuItem4x";
            this.menuItem4x.Size = new System.Drawing.Size(152, 22);
            this.menuItem4x.Text = "4x";
            this.menuItem4x.Click += new System.EventHandler(this.menuItem4x_Click);
            // 
            // menuItemRound
            // 
            this.menuItemRound.Checked = true;
            this.menuItemRound.CheckState = System.Windows.Forms.CheckState.Checked;
            this.menuItemRound.Name = "menuItemRound";
            this.menuItemRound.Size = new System.Drawing.Size(152, 22);
            this.menuItemRound.Text = "Round";
            this.menuItemRound.Click += new System.EventHandler(this.menuItemRound_Click);
            // 
            // menuItemHide
            // 
            this.menuItemHide.Name = "menuItemHide";
            this.menuItemHide.Size = new System.Drawing.Size(152, 22);
            this.menuItemHide.Text = "Hide";
            this.menuItemHide.Click += new System.EventHandler(this.menuItemHide_Click);
            // 
            // TransparentColorDialog
            // 
            this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
            this.ClientSize = new System.Drawing.Size(200, 200);
            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
            this.Name = "TransparentColorDialog";
            this.ShowInTaskbar = false;
            this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
            this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
            this.contextMenuSizeX.ResumeLayout(false);
            this.ResumeLayout(false);

		}
		#endregion

		public bool Circle
		{
			get	{ return _isCircle;	}
			set { 

				if( _isCircle == value) return;

				_isCircle = value;

				this.menuItemRound.Checked = value;

				if( _txForm != null) _txForm.Circle = value;


				Invalidate();
			}
		}



		private void tf_MouseDown(object sender, MouseEventArgs e)
		{
            if (TxMouseDown != null) TxMouseDown(this, e);

			if( e.Button == MouseButtons.Left) 
			{
				_colorDialogMoving	= true;
				_mousePosition		= Control.MousePosition; 
			}

		}

		private void tf_MouseUp(object sender, MouseEventArgs e)
		{
            if (TxMouseUp != null) TxMouseUp(this, e);
            if (e.Button == MouseButtons.Left) _colorDialogMoving = false;		
		}

		private void tf_MouseMove(object sender, MouseEventArgs e)
		{
            if (TxMouseMove != null) TxMouseMove(this, e);

			if( _colorDialogMoving )
			{
				
				Point newPosition = Control.MousePosition;
				
				int dx = newPosition.X - _mousePosition.X;
				int dy = newPosition.Y - _mousePosition.Y;
				Point thisLocation = this.Location;
				thisLocation.X+= dx;
				thisLocation.Y+= dy;
				this.Location = thisLocation;

				_mousePosition		= newPosition; 
			}

		}

		protected override void OnLocationChanged(EventArgs e)
		{
			if( _txForm != null)
			{
				Rectangle tfBounds = this.RectangleToScreen( this.ClientRectangle );
				tfBounds.Inflate( -OFFSET_BORDER,-OFFSET_BORDER);
				_txForm.Bounds = tfBounds;
			}

			base.OnLocationChanged (e);
		}

		protected override void OnVisibleChanged(EventArgs e)
		{
			base.OnVisibleChanged (e);
			if( _txForm != null) _txForm.Visible = this.Visible;
		}

		protected override void OnSizeChanged(EventArgs e)
		{
			if( _txForm != null)
			{
				Rectangle tfBounds = this.RectangleToScreen( this.ClientRectangle );
				tfBounds.Inflate( -OFFSET_BORDER,-OFFSET_BORDER);
				_txForm.Bounds = tfBounds;
			}
			base.OnSizeChanged (e);
		}

		protected override void OnPaintBackground(PaintEventArgs e)
		{
            base.OnPaintBackground (e);
			

			if( !_isCircle)
			{
				using ( Pen pen = new Pen( SystemColors.ControlDarkDark, 2f))
					e.Graphics.DrawRectangle( pen, this.ClientRectangle );
			}
			else
			{
				Rectangle r = this.ClientRectangle;
				r.Width--; r.Height--;

				using ( Pen pen = new Pen( SystemColors.ControlDarkDark, 1f))
					e.Graphics.DrawEllipse( pen, r );
			}

		}

		protected override void OnGotFocus(EventArgs e)
		{
			base.OnGotFocus (e);
			if( _txForm != null) _txForm.TopMost = true;
			this.TopMost = true;
		}
 
		[Browsable( false)]
		public SizeX SizeNX
		{
			get{ return _sizeX;}
			set
			{
				if( _sizeX == value ) return;

				menuItem1x.Checked = value == SizeX.Size1X;
				menuItem2x.Checked = value == SizeX.Size2X;
				menuItem3x.Checked = value == SizeX.Size3X;
				menuItem4x.Checked = value == SizeX.Size4X;

				if( value == SizeX.Size1X ) this.Size = new Size( 100,100);
				if( value == SizeX.Size2X ) this.Size = new Size( 200,200);
				if( value == SizeX.Size3X ) this.Size = new Size( 300,300);
				if( value == SizeX.Size4X ) this.Size = new Size( 400,400);
 
				_sizeX = value;
				
				this.Invalidate();
			}
		}

		private void menuItem1x_Click(object sender, System.EventArgs e)
		{
			this.SizeNX = SizeX.Size1X;
		}

		private void menuItem2x_Click(object sender, System.EventArgs e)
		{
			this.SizeNX = SizeX.Size2X;
		}

		private void menuItem3x_Click(object sender, System.EventArgs e)
		{
			this.SizeNX = SizeX.Size3X;
		}

		private void menuItem4x_Click(object sender, System.EventArgs e)
		{
			this.SizeNX = SizeX.Size4X;
		}

		private void menuItemRound_Click(object sender, System.EventArgs e)
		{
			menuItemRound.Checked = !menuItemRound.Checked;
			this.Circle = menuItemRound.Checked;
		}

        private void menuItemHide_Click(object sender, EventArgs e)
        {
            this.Visible = false;
            if (TxHidden != null) TxHidden(sender, e);
        }

		private class TransparentForm: System.Windows.Forms.Form
		{
			private bool _isCircle = true;

            public TransparentForm(ContextMenuStrip contextMenu, bool circle)
			{
				this.SetStyle( ControlStyles.DoubleBuffer, true);

                this.FormBorderStyle = FormBorderStyle.None;

                ResetOpacityValue();

                this.ContextMenuStrip = contextMenu;

                ColorRenderingValue.OpacityChanged+=new EventHandler(ColorRenderingValue_OpacityChanged);
				ColorRenderingValue.ValueChanged+=new EventHandler(ColorRenderingValue_ValueChanged);

                this.BackColor = Color.FromArgb(255, ColorRenderingValue.Color);

                this.Cursor = Cursors.SizeAll;

                this.Circle = circle;

			}


            private void ResetOpacityValue()
            {
                double crOpacity = ColorRenderingValue.Opacity;

                if (_isCircle && crOpacity == 255.0) crOpacity = 254.0;//fasten moving when 255;
                if (crOpacity < 1.0) crOpacity = 1.0;

                this.Opacity = crOpacity / 255.0;

            }

			public bool Circle
			{
				set
				{
					if( value == _isCircle) return;

					if( value )
					using(GraphicsPath p = new GraphicsPath())
					{
						Rectangle r = this.ClientRectangle;
						r.Width--; r.Height--;
						p.AddEllipse( r );
						this.Region = new Region(p);
					}
					else this.Region = null;

					_isCircle = value;
					
				}
			}

			protected override void OnVisibleChanged(EventArgs e)
			{
				if( this.Visible)
				{
                    ResetOpacityValue();
		
                    this.BackColor = Color.FromArgb(255, ColorRenderingValue.Color);
				}

				base.OnVisibleChanged (e);
			}

		
			private void ColorRenderingValue_OpacityChanged(object sender, EventArgs e)
			{
				if( this.Visible)   ResetOpacityValue();
			}

			private void ColorRenderingValue_ValueChanged(object sender, EventArgs e)
			{
				if( this.Visible)
					this.BackColor = Color.FromArgb(255, ColorRenderingValue.Color);
			}


			protected override void OnSizeChanged(EventArgs e)
			{

				if( _isCircle)
				using(GraphicsPath p = new GraphicsPath())
				{
					Rectangle r = this.ClientRectangle;
					r.Width--; r.Height--;
					p.AddEllipse( r );
					this.Region = new Region(p);
				}
				
				base.OnSizeChanged (e);
			}

			protected override void OnClosing(CancelEventArgs e)
			{
				e.Cancel = true;
				base.OnClosing (e);
			}

		}

	}
}
